package mobile.game.core.gen.serializer;

import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.google.protobuf.GeneratedMessage;

import mobile.game.core.gen.GenBase;
import mobile.game.core.support.ClassFinder;

/**
 * @author gaopan
 *
 * 生成MsgSerializer
 */
public class GenMsgSerializer extends GenBase {
	private static final String GEN_CLASS_NAME = "MsgSerializer";
	private static final String FTL_FILE_NAME = "MsgSerializer.ftl";
	private static final Class<?> ANNO_CLASS = GeneratedMessage.class;

	public GenMsgSerializer(String packageName, String targetDir) throws Exception {
		super(packageName, targetDir);
		this.init();
	}
	
	/**
	 * 初始化class信息，是否能生成等字段
	 * @throws Exception
	 */
	private void init() throws Exception {
		/**  默认是true */
		this.canGen = true;
		
		// 遍历所有类信息, 获取模板信息, 判断是否出错, 出错则初始化异常不能生成
		List<Class<?>> classes = getClassInfoToGen();
		for(Class<?> clazz : classes) {
			try {
				this.rootMaps.add(getRootMap(clazz));
			} catch (Exception e) {
				// 如果获取模板内容异常，表示不能生成
				/**  不能生成 */
				this.canGen = false;
				System.err.println("文件存在错误，不继续进行Observer生成了，错误如下：");
				e.printStackTrace();
			}
		}
		
	}
	
	/**
	 * 生成Proxy类的核心方法
	 * @param rootMap
	 * @throws Exception
	 */
	
	@Override
	protected void genFileHandler(Map<String, Object> rootMap) throws Exception {

	}

	@Override
	protected void genGlobalFileHandler(Map<String, Object> rootMaps) throws Exception {
		rootMaps.put("rootClassName", GEN_CLASS_NAME);
		rootMaps.put("interfaceName", ANNO_CLASS.getName());
		
		String targetFileDir = this.targetDir + ClassFinder.packageToPath(this.packageName) + "/";
		writeFile(targetFileDir, GEN_CLASS_NAME + ".java", FTL_FILE_NAME, rootMaps);
	}

	/**
	 * 获取要生成的class及其method
	 * @return
	 * @throws Exception
	 */
	private List<Class<?>> getClassInfoToGen() throws Exception {
		List<Class<?>> result = new LinkedList<>();
		// 获取源文件夹下的所有类
		List<Class<?>> sources = ClassFinder.getAllClass(packageName);
		
		// 遍历所有类，取出类中有@相应注解的方法
		//ClassPool pool = ClassPool.getDefault();
		for(Class<?> clazz : sources) {
			int mod = clazz.getModifiers();
			if(Modifier.isInterface(mod) || Modifier.isAbstract(mod))
				continue;
			if(!Modifier.isPublic(mod))
				continue;
			
			if(!ANNO_CLASS.isAssignableFrom(clazz)) {
				continue;
			}

			result.add(clazz);
		}
		
		return result;
	}
	
	/**
	 * 根据Class及其methods获取填充模板内容
	 * @param clazz
	 * @param methods
	 * @return
	 * @throws Exception 
	 */
	private Map<String, Object> getRootMap(Class<?> clazz) throws Exception {
		// 获取实体类名,表名,包名
  		// String packageName = clazz.getPackage().getName();
  		
		String className = clazz.getName();
		className = className.replace('$','.');
		int id = clazz.getName().hashCode();
		// 填充Map
		Map<String, Object> rootMap = new HashMap<>();
		rootMap.put("className", className);
		rootMap.put("id", String.valueOf(id));
		
		return rootMap;
	}

	public static void main(String[] args) throws Exception {
		if(args.length < 2) {
			System.out.println("usage: packageName, targetDir");
			return;
		}
		
		//设置log4j2配置文件所需的环境变量，作用是gen的时候
		//不会报配置没找到的错误，同时有gen.log的日志记录
		System.setProperty("logFileName", "GenMsgSerializer");
		
		String packageName = args[0];
		String targetDir = System.getProperty("user.dir") + args[1];
		
		GenBase genMsgSerializer = new GenMsgSerializer(packageName, targetDir);
		
		// 判断不能生成Entity
		if(!genMsgSerializer.isCanGen()) {
			System.err.println("不能生成MsgSerializer，请检查重试。。");
			return;
		}
		
		// 测试生成实体类
		genMsgSerializer.genFiles();
	}

}
